#include "RandomBoost.h"
#include <boost/generator_iterator.hpp>
//Test:
#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <boost/regex.hpp>
#include <string>

namespace jcrada {

    RandomBoost::RandomBoost() {
        rng = new RandomNumberGenerator(static_cast<unsigned int> (std::time(0)));
    }

    RandomBoost::RandomBoost(unsigned int seed) {
        rng = new RandomNumberGenerator(seed);

    }

    RandomBoost::~RandomBoost() {
        delete rng;
    }

    bool RandomBoost::nextBool() {
        return nextDouble() > 0.5;
    }

    double RandomBoost::nextDouble() {
        static boost::uniform_real<> distribution(0, 1);
        GeneratorReal gt(*rng, distribution);
        boost::generator_iterator<GeneratorReal> die(&gt);
        return *die++;
    }

    double RandomBoost::nextDouble(double min, double max) {
        boost::uniform_real<> distribution(min, max);
        GeneratorReal gt(*rng, distribution);
        boost::generator_iterator<GeneratorReal> die(&gt);
        return *die++;
    }

    float RandomBoost::nextFloat() {
        static boost::uniform_real<> distribution(0, 1);
        GeneratorReal gt(*rng, distribution);
        boost::generator_iterator<GeneratorReal> die(&gt);
        return *die++;
    }

    float RandomBoost::nextFloat(float min, float max) {
        boost::uniform_real<> distribution(min, max);
        GeneratorReal gt(*rng, distribution);
        boost::generator_iterator<GeneratorReal> die(&gt);
        return *die++;
    }

    int RandomBoost::nextInt() {
        static boost::uniform_int<> distribution(0, UINT_MAX);
        GeneratorInt gt(*rng, distribution);
        boost::generator_iterator<GeneratorInt> die(&gt);
        return *die++;
    }

    int RandomBoost::nextInt(int min, int max) {
        boost::uniform_int<> distribution(min, max);
        GeneratorInt gt(*rng, distribution);
        boost::generator_iterator<GeneratorInt> die(&gt);
        return *die++;
    }

    long RandomBoost::nextLong() {
        static boost::uniform_int<> distribution(0, ULONG_MAX);
        GeneratorInt gt(*rng, distribution);
        boost::generator_iterator<GeneratorInt> die(&gt);
        return *die++;
    }

    long RandomBoost::nextLong(long min, long max) {
        boost::uniform_int<> distribution(min, max);
        GeneratorInt gt(*rng, distribution);
        boost::generator_iterator<GeneratorInt> die(&gt);
        return *die++;
    }

    void RandomBoost::setSeed(long seed) {
        rng->seed(static_cast<unsigned int> (seed));
    }

    class Test {
    public:

        static int testMain() {
            using namespace boost::lambda;
            typedef std::istream_iterator<int> in;

            std::for_each(
                    in(std::cin), in(), std::cout << (_1 * 3) << " ");

            return 0;
        }

        static void testRegEx() {
            std::string line;
            boost::regex pat("^[a-z]{1,}$");
            boost::regex out_pattern("^quit$");

            while (std::cin) {
                std::getline(std::cin, line);
                boost::smatch matches;
                if (boost::regex_match(line, matches, out_pattern)) {
                    std::cout << "good bye :)" << std::endl;
                    break;
                }
                if (boost::regex_match(line, matches, pat)) {
                    std::cout << "Matched! : " << matches[1] << std::endl;
                }
            }
        }
    };

}